﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UMLSynthesizer.LangAnalyzer;
using UMLSynthesizer.LangAnalyzer.Elements;
using UMLSynthesizer.LangAnalyzer.ExtensionMethods;
using UMLSynthesizer.Tasks.View;
using UMLSynthesizer.Tasks.ViewModel;

namespace UMLSynthesizer.Tasks
{
    public class SelectProjectTask : ITaskBase
    {
        #region Declarations

        /// <summary>
        /// The printable name for this task
        /// </summary>
        public const string DisplayName = "Select project";

        /// <summary>
        /// Used reading parameters
        /// </summary>
        enum TaskParameterSection { NoPhase, SourceSelection };

        /// <summary>
        /// States of the task
        /// </summary>
        public enum SelectionTaskState
        {
            Aborted,
            Error_NoAnalyzer,
            NoCodeSelected,
            ProjectSelected,
            Ready,
            Running
        };

        #endregion

        #region Properties

        /// <summary>
        /// The state of the selection task
        /// </summary>
        public SelectionTaskState CurrentState { get; private set; }
        /// <summary>
        /// The selected language analyzer
        /// </summary>
        public LanguageAnalyzer SelectedLanguageAnalyzer { get; private set; }
        /// <summary>
        /// The selected source code project
        /// </summary>
        public IProjectElement SelectedProject { get; private set; }

        #endregion

        #region Public Interface

        /// <summary>
        /// Constructor
        /// </summary>
        public SelectProjectTask()
        {
            CurrentState = SelectionTaskState.Ready;
        }

        /// <summary>
        /// Start the task. It's the entry point
        /// </summary>
        /// <param name="parameters">
        /// Parameter options:
        ///     -silent: don't show any interface and try to use only parameters
        ///     -sourceSelection [source selector parameters]: define parameters for the source selection phase
        /// </param>
        public void StartTask(IEnumerable<string> parameters = null)
        {
            CurrentState = SelectionTaskState.Running;

            //Read parameters
            bool isForcedSilent = false;
            TaskParameterSection currentParameterPhaseTarget = TaskParameterSection.NoPhase;
            List<string> sourceSelectorParameters = new List<string>();
            if(parameters != null)
                foreach (var parameter in parameters)
                    switch(parameter.ToLower())
                    {
                        case "-silent":
                            isForcedSilent = true;
                            break;

                        case "-sourceselection":
                            currentParameterPhaseTarget = TaskParameterSection.SourceSelection;
                            break;

                        default:
                            switch(currentParameterPhaseTarget)
                            {
                                case TaskParameterSection.NoPhase:
                                    throw new ArgumentException("Invalid parameter: " + parameter);
                                case TaskParameterSection.SourceSelection:
                                    sourceSelectorParameters.Add(parameter);
                                    break;
                            }
                            break;
                    }

            //Prepare View and ViewModel
            var SCSelectorWindow = new SourceCodeSelectorWindow();
            var SCSelectorViewModel = new SourceCodeSelectorViewModel(
                new Language[] { Language.CSharp /*, Language.Cpp, Language.Java*/ },
                sourceSelectorParameters.ToArray());

            EventHandler handler = null;
            handler = delegate
            {
                SCSelectorViewModel.RequestClose -= handler;
                SCSelectorWindow.Close();
            };
            SCSelectorViewModel.RequestClose += handler;

            //Select source code, try silent
            if (isForcedSilent && SCSelectorViewModel.StartScanAndCloseCommand.CanExecute(null))
                SCSelectorViewModel.StartScanAndCloseCommand.Execute(null);
            else
            {
                SCSelectorWindow.DataContext = SCSelectorViewModel;
                SCSelectorWindow.ShowDialog();
            }

            if (!SCSelectorViewModel.ExitStateOK)
            {
                CurrentState = SelectionTaskState.Aborted;
                return;
            }

            //Process source code
            if (SCSelectorViewModel.SourceFiles.Count() == 0)
            {
                CurrentState = SelectionTaskState.NoCodeSelected;
                return;
            }
            if (!SCSelectorViewModel.SelectedLanguage.HasAnalyzer)
            {
                CurrentState = SelectionTaskState.Error_NoAnalyzer;
                return;
            }

            SelectedProject = SCSelectorViewModel.SelectedLanguage.Analyzer.GetProject(SCSelectorViewModel.SourceFiles);
            SelectedLanguageAnalyzer = SCSelectorViewModel.SelectedLanguage.Analyzer;

            CurrentState = SelectionTaskState.ProjectSelected;
        }

        #endregion
    }
}
